﻿using System;
using System.Diagnostics;

namespace PacketRush.Core
{
    /// <summary>
    /// Base interface for providing shared functionality between
    /// <see cref="PacketRush.Core.IClientNetworkingProvider"/> and <see cref="PacketRush.Core.IServerNetworkingProvider"/>.
    /// </summary>
    public interface INetworkingProvider
    {
        /// <summary>
        /// Raised when this provider encounters an error.
        /// </summary>
        Action<NetErrorEventArgs> ErrorAction { get; set; }

        /// <summary>
        /// Called when the provider receives packets.
        /// </summary>
        /// <remarks>
        /// <para>
        /// When implementing a custom networking provider, <c>ReceivePacketAction</c> should be called for every packet received during
        /// a <see cref="PacketRush.Core.INetworkingProvider.Receive"/> call.
        /// </para>
        /// <para>
        /// See <see cref="PacketRush.Core.INetworkingProvider.Receive"/> for additional details.
        /// </para>
        /// </remarks>
        Action<byte[], INetConnection> ReceivePacketAction { get; set; }

        /// <summary>
        /// The amount of time the networking provider has been running.
        /// </summary>
        NetTime RunningTime { get; set; }

        /// <summary>
        /// Send a packet to the given connection reliably.
        /// </summary>
        /// <param name="target">The target connection to send to.</param>
        /// <param name="packet">The raw packet to send.</param>
        void SendReliable(INetConnection target, byte[] packet);

        /// <summary>
        /// Send a packet to the given connection unreliably.
        /// </summary>
        /// <param name="target">The target connection to send to.</param>
        /// <param name="packet">The raw packet to send.</param>
        void SendUnreliable(INetConnection target, byte[] packet);

        /// <summary>
        /// Receives network packets.
        /// </summary>
        /// <remarks>
        /// Implementations of Receive should call <see cref="PacketRush.Core.INetworkingProvider.ReceivePacketAction"/>
        /// for each packet received from the network, this reduces the need to queue or store packets before passing them
        /// up to <see cref="PacketRush.Core.NetServer"/> and <see cref="PacketRush.Core.NetClient"/>.
        /// </remarks>
        void Receive();

        /// <summary>
        /// Disconnect this provider from the network.
        /// </summary>
        void Disconnect();

        /// <summary>
        /// Perform any other work, useful if any state needs to be updated or pending operations
        /// need to be acted upon.
        /// </summary>
        void Update();
    }
}
